#include "stdafx.h"
#include "CppUnitTest.h"

#include "TestFiles.h"

#include "ImageProcSteps.h"

#include "ImageExpt.h"
#include "ProcParam.h"
#include "ProcParamDouble.h"
#include "ProcParamInt.h"
#include "ProcParamString.h"
#include "ProcParams.h"
#include "ProcParamsOutputs.h"
#include "ProcParamsInputs.h"


using namespace Microsoft::VisualStudio::CppUnitTestFramework;

namespace PluginICProcStepsTest
{
	TEST_CLASS(ProcParamXmlTest)
	{
	private:
		ImageExpt	      *_ief;
		TiXmlElement      *_procStepsXml;
		TiXmlElement	  *_step; 
		TiXmlElement	  *_inputs;
		TiXmlElement	  *_outputs;

	public:

		TEST_METHOD_INITIALIZE(InitProcParamXmlTest)
		{
			if ((_ief = ImageExpt::CreateImageExpt(TestFiles::UnitTestIEFwStr, '\0', L"unit test", L"default", ImageExpt::FromDefaults)) != '\0')
			{
				if ((_procStepsXml = _ief->GetHeaderProcSteps()) != '\0')
				{
					if ((_step = TinyXmlLib::CreateSection (_procStepsXml, ImageProcStep::xmlProcStep, "(give description of step here)" )) != '\0')
					{
						_step->SetAttribute(ImageProcStep::attribStepNum, 1);
						_step->SetAttribute(ImageProcStep::attribLibName,  "test.dll" );
						_step->SetAttribute(ImageProcStep::attribLibVersion, "v1.0.0.0");
						_step->SetAttribute(ImageProcStep::attribInterfaceVersion,1);
						_step->SetAttribute(ImageProcStep::attribFunctionName,"TestFn");
						_inputs = TinyXmlLib::CreateSection (_step, ProcParamsInputs::xmlInputs, "TestFn");
						_outputs = TinyXmlLib::CreateSection (_step, ProcParamsOutputs::xmlOutputs, "TestFn");
					}
				}
			}
		}

		TEST_METHOD_CLEANUP(DeinitProcParamXmlTest)
		{

			if (_ief != '\0')
				delete _ief;
			_ief = '\0';
		}

		
		TEST_METHOD(CreateIEFXmlFileTest)
		{
			Assert::IsNotNull(_ief);
			Assert::IsNotNull(_procStepsXml);
			Assert::AreEqual( ImageProcSteps::xmlProcSteps, _procStepsXml->Value());
			Assert::IsNotNull(_step);
			Assert::AreEqual( ImageProcStep::xmlProcStep,  _step->Value());
			Assert::IsNotNull(_inputs);
			Assert::AreEqual( ProcParamsInputs::xmlInputs,  _inputs->Value());
			Assert::IsNotNull(_outputs);
			Assert::AreEqual( ProcParamsOutputs::xmlOutputs,  _outputs->Value());
		}

		TEST_METHOD(DeleteInputsTest)
		{
			_inputs->SetAttribute(ProcParams::attribParamCnt, 0);

			ProcParamsInputs *inputs = '\0';
			Assert::IsNotNull(inputs = new ProcParamsInputs(_step));
			Assert::IsFalse(inputs->IsValid());
			Assert::IsFalse(inputs->Validate());	//must contain at least one parameter
			delete inputs;
		}

		TEST_METHOD(Load1InputParamFromXmlTest)
		{
			_inputs->SetAttribute(ProcParams::attribParamCnt, 1);
			TiXmlElement *xmlElementForParam = TinyXmlLib::CreateSection (_inputs, IPluginICProcStepsParamXmlProcParam, "5");
			xmlElementForParam->SetAttribute(IPluginICProcStepsParamAttribName, "a");
			xmlElementForParam->SetAttribute(IPluginICProcStepsParamAttribIndex, 0);
			xmlElementForParam->SetAttribute(IPluginICProcStepsParamAttribType, IPluginICProcStepsParamDefIntP);

			ProcParamsInputs *inputs = '\0';
			Assert::IsNotNull(inputs = new ProcParamsInputs(_step));
			Assert::IsFalse(inputs->IsValid());
			Assert::IsTrue( inputs->Validate());
			Assert::IsTrue( inputs->IsValid());
			Assert::AreEqual( 1, inputs->GetParamCount());
			Assert::AreEqual( 0, inputs->GetParam("a")->GetIndex());
			delete inputs;
		}

		TEST_METHOD(Load2InputParamFromXmlTest)
		{
			_inputs->SetAttribute(ProcParams::attribParamCnt, 2);
			TiXmlElement *xmlElementForParam1 = TinyXmlLib::CreateSection (_inputs, IPluginICProcStepsParamXmlProcParam, "5");
			xmlElementForParam1->SetAttribute(IPluginICProcStepsParamAttribName, "a");
			xmlElementForParam1->SetAttribute(IPluginICProcStepsParamAttribIndex, 0);
			xmlElementForParam1->SetAttribute(IPluginICProcStepsParamAttribType, IPluginICProcStepsParamDefIntP);

			TiXmlElement *xmlElementForParam2 = TinyXmlLib::CreateSection (_inputs, IPluginICProcStepsParamXmlProcParam, "5");
			xmlElementForParam2->SetAttribute(IPluginICProcStepsParamAttribName, "b");
			xmlElementForParam2->SetAttribute(IPluginICProcStepsParamAttribIndex, 1);
			xmlElementForParam2->SetAttribute(IPluginICProcStepsParamAttribType, IPluginICProcStepsParamDefIntP);

			ProcParamsInputs *inputs = '\0';
			Assert::IsNotNull(inputs = new ProcParamsInputs(_step));
			Assert::IsTrue(inputs->Validate());
			Assert::IsTrue( inputs->IsValid());
			Assert::AreEqual( 2, inputs->GetParamCount());
			Assert::AreEqual( 0, inputs->GetParam("a")->GetIndex());
			Assert::AreEqual( 1, inputs->GetParam("b")->GetIndex());

			ProcParamInt *val = dynamic_cast<ProcParamInt *>(inputs->GetParam("b"));
			Assert::IsNotNull(val);
			val->SetValue(3);
			Assert::AreEqual( 3, val->GetValue());
			delete inputs;
		}

		TEST_METHOD(Load2OutputParamFromXmlTest)
		{
			_outputs->SetAttribute(ProcParams::attribParamCnt, 2);
			TiXmlElement *xmlElementForParam1 = TinyXmlLib::CreateSection (_outputs, IPluginICProcStepsParamXmlProcParam, "5");
			xmlElementForParam1->SetAttribute(IPluginICProcStepsParamAttribName, IPluginICProcStepsParamAttribOutputNameResult);
			xmlElementForParam1->SetAttribute(IPluginICProcStepsParamAttribIndex, 0);
			xmlElementForParam1->SetAttribute(IPluginICProcStepsParamAttribType, IPluginICProcStepsParamDefIntP);

			TiXmlElement *xmlElementForParam2 = TinyXmlLib::CreateSection (_outputs, IPluginICProcStepsParamXmlProcParam, "5");
			xmlElementForParam2->SetAttribute(IPluginICProcStepsParamAttribName, "b");
			xmlElementForParam2->SetAttribute(IPluginICProcStepsParamAttribIndex, 1);
			xmlElementForParam2->SetAttribute(IPluginICProcStepsParamAttribType, IPluginICProcStepsParamDefIntP);

			ProcParamsOutputs *outputs = '\0';
			Assert::IsNotNull(outputs = new ProcParamsOutputs(_step));
			Assert::IsFalse(outputs->IsValid());
			Assert::IsTrue(outputs->Validate());
			Assert::IsTrue( outputs->IsValid());
			Assert::AreEqual( 2, outputs->GetParamCount());
			Assert::AreEqual( 0, outputs->GetParam(IPluginICProcStepsParamAttribOutputNameResult)->GetIndex());
			Assert::AreEqual( 1, outputs->GetParam("b")->GetIndex());
			Assert::IsTrue(outputs->SetParamValue("b", 3));
			ProcParamInt *val = dynamic_cast<ProcParamInt *>(outputs->GetParam("b"));
			Assert::IsNotNull(val);
			Assert::AreEqual(  3, val->GetValue());

			Assert::AreEqual( 0, ProcParamsOutputs::ResultOK);
			Assert::IsTrue(outputs->SetResultCode(ProcParamsOutputs::ResultOK));
			Assert::IsTrue(outputs->IsResultOK());
			Assert::AreEqual( 0, outputs->GetResultCode());		
	
			Assert::IsFalse(outputs->IsAnalysisSet());
			Assert::IsFalse(outputs->SetScore(0.0));
			Assert::AreEqual( ProcParamsOutputs::ScoreInvalid, outputs->GetScore());
			delete outputs;
		}

		TEST_METHOD(LoadNullParamFromXmlTest)
		{
			ProcParamsInputs *inputs = '\0';
			TiXmlElement *stepXml = '\0'; 
			Assert::IsNotNull(inputs = new ProcParamsInputs(stepXml));
			Assert::IsFalse(inputs->Validate());
			Assert::IsFalse(inputs->IsValid());
			Assert::AreEqual( ProcParams::NotFound, inputs->GetParamCount());
			delete inputs;
		}

		TEST_METHOD(Load1ParamFromInvalidXmlTest)
		{
			_inputs->SetAttribute(ProcParams::attribParamCnt, 1);
			TiXmlElement *xmlElementForParam = TinyXmlLib::CreateSection (_inputs, IPluginICProcStepsParamXmlProcParam, "5");
			xmlElementForParam->SetAttribute(IPluginICProcStepsParamAttribName, "a");
			xmlElementForParam->SetAttribute(IPluginICProcStepsParamAttribIndex, 0);
			xmlElementForParam->SetAttribute(IPluginICProcStepsParamAttribType, IPluginICProcStepsParamDefIntP);

			ProcParamsInputs *inputs = '\0';
			Assert::IsNotNull(inputs = new ProcParamsInputs(xmlElementForParam));
			Assert::IsFalse( inputs->Validate());	//need to pass ctor ImageProcStep::xmlProcStep not IPluginICProcStepsParamXmlProcParam
			Assert::IsFalse(inputs->IsValid());
			delete inputs;
		}

		TEST_METHOD(Load1ParamFromNoxmlInputsXmlTest)
		{
			//delete _inputs;
			//_inputs = TinyXmlLib::CreateSection (_step, "xxxx", "TestFn");

			//_inputs->SetAttribute(ProcParams::attribParamCnt, 1);
			//TiXmlElement *xmlElementForParam = TinyXmlLib::CreateSection (_inputs, IPluginICProcStepsParamXmlProcParam, "5");
			//xmlElementForParam->SetAttribute(IPluginICProcStepsParamAttribName, "a");
			//xmlElementForParam->SetAttribute(IPluginICProcStepsParamAttribIndex, 0);
			//xmlElementForParam->SetAttribute(IPluginICProcStepsParamAttribType, IPluginICProcStepsParamDefIntP);

			//ProcParamsInputs *inputs = '\0';
			//Assert::IsNotNull(inputs = new ProcParamsInputs(_step));
			//Assert::IsFalse(inputs->IsValid());
			//Assert::IsFalse(inputs->Validate());
			//delete inputs;
		}

		TEST_METHOD(Load1ParamFromNoParamCntXmlTest)
		{
			_inputs->SetAttribute(ProcParams::attribParamCnt, 1);
			TiXmlElement *xmlElementForParam = TinyXmlLib::CreateSection (_inputs, IPluginICProcStepsParamXmlProcParam, "5");
			xmlElementForParam->SetAttribute(IPluginICProcStepsParamAttribName, "a");
			xmlElementForParam->SetAttribute(IPluginICProcStepsParamAttribIndex, 0);
			xmlElementForParam->SetAttribute(IPluginICProcStepsParamAttribType, IPluginICProcStepsParamDefIntP);

			ProcParamsInputs *inputs = '\0';
			Assert::IsNotNull(inputs = new ProcParamsInputs(xmlElementForParam));
			Assert::IsFalse(inputs->Validate());	//ProcParams::attribParamCnt not set
			Assert::IsFalse(inputs->IsValid());
			delete inputs;
		}

		TEST_METHOD(Load1ParamFromBadParamCntXmlTest)
		{
			_inputs->SetAttribute(ProcParams::attribParamCnt, 1);		//one not two
			TiXmlElement *xmlElementForParam1 = TinyXmlLib::CreateSection (_inputs, IPluginICProcStepsParamXmlProcParam, "5");
			xmlElementForParam1->SetAttribute(IPluginICProcStepsParamAttribName, "a");
			xmlElementForParam1->SetAttribute(IPluginICProcStepsParamAttribIndex, 0);
			xmlElementForParam1->SetAttribute(IPluginICProcStepsParamAttribType, IPluginICProcStepsParamDefIntP);

			TiXmlElement *xmlElementForParam2 = TinyXmlLib::CreateSection (_inputs, IPluginICProcStepsParamXmlProcParam, "5");
			xmlElementForParam2->SetAttribute(IPluginICProcStepsParamAttribName, "b");
			xmlElementForParam2->SetAttribute(IPluginICProcStepsParamAttribIndex, 1);
			xmlElementForParam2->SetAttribute(IPluginICProcStepsParamAttribType, IPluginICProcStepsParamDefIntP);

			ProcParamsInputs *inputs = '\0';
			Assert::IsNotNull(inputs = new ProcParamsInputs(_step));
			Assert::IsFalse(inputs->Validate());
			Assert::IsFalse(inputs->IsValid());
			delete inputs;
		}

		TEST_METHOD(LoadDupInputParamFromXmlTest)
		{
			_inputs->SetAttribute(ProcParams::attribParamCnt, 2);
			TiXmlElement *xmlElementForParam1 = TinyXmlLib::CreateSection (_inputs, IPluginICProcStepsParamXmlProcParam, "5");
			xmlElementForParam1->SetAttribute(IPluginICProcStepsParamAttribName, "a");
			xmlElementForParam1->SetAttribute(IPluginICProcStepsParamAttribIndex, 0);
			xmlElementForParam1->SetAttribute(IPluginICProcStepsParamAttribType, IPluginICProcStepsParamDefIntP);

			TiXmlElement *xmlElementForParam2 = TinyXmlLib::CreateSection (_inputs, IPluginICProcStepsParamXmlProcParam, "5");
			xmlElementForParam2->SetAttribute(IPluginICProcStepsParamAttribName, "a");
			xmlElementForParam2->SetAttribute(IPluginICProcStepsParamAttribIndex, 0);
			xmlElementForParam2->SetAttribute(IPluginICProcStepsParamAttribType, IPluginICProcStepsParamDefIntP);

			ProcParamsInputs *inputs = '\0';
			Assert::IsNotNull(inputs = new ProcParamsInputs(_step));
			Assert::IsFalse(inputs->Validate());			//Para2 has same name and index
			Assert::IsFalse(inputs->IsValid());
			delete inputs;

			xmlElementForParam2->SetAttribute(IPluginICProcStepsParamAttribName, "b");
			Assert::IsNotNull(inputs = new ProcParamsInputs(_step));
			Assert::IsFalse( inputs->Validate());			//Para2 has same index
			Assert::IsFalse(inputs->IsValid());
			delete inputs;

			xmlElementForParam2->SetAttribute(IPluginICProcStepsParamAttribIndex, 2);
			Assert::IsNotNull(inputs = new ProcParamsInputs(_step));
			Assert::IsFalse( inputs->Validate());			//index 1 missing
			Assert::IsFalse( inputs->IsValid());
			delete inputs;

			xmlElementForParam2->SetAttribute(IPluginICProcStepsParamAttribIndex, 1);
			Assert::IsNotNull(inputs = new ProcParamsInputs(_step));
			Assert::IsTrue(inputs->Validate());			//ok
			Assert::IsTrue(inputs->IsValid());
			delete inputs;
		}
	};
}